package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.ActivityFeignClient;
import cn.com.dcsgo.ProductFeignClient;
import cn.com.dcsgo.enums.SkuType;
import cn.com.dcsgo.model.product.Category;
import cn.com.dcsgo.model.product.SkuInfo;
import cn.com.dcsgo.model.search.SkuEs;
import cn.com.dcsgo.repository.SkuRepository;
import cn.com.dcsgo.security.AuthContextHolder;
import cn.com.dcsgo.service.SkuService;
import cn.com.dcsgo.vo.search.SkuEsQueryVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * SkuServiceImpl
 *
 * @author Dcsgo
 * @since 2025/4/17 上午11:16
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SkuServiceImpl implements SkuService {
    private final SkuRepository skuRepository;
    private final ProductFeignClient productFeignClient;
    private final ActivityFeignClient activityFeignClient;
    private final RedisTemplate<Object, Object> redisTemplate;

    @Override
    public void deleteById(Long id) {
        skuRepository.deleteById(id);
    }

    @Override
    public void insertById(Long id) {
        //获取sku基本信息及其分类信息
        SkuInfo skuInfo = productFeignClient.getSkuInfoById(id);
        if (skuInfo == null) {
            //没有获取到相关的sku信息，无须再执行后续的添加操作
            return;
        }
        Category category = productFeignClient.getCategoryById(skuInfo.getCategoryId());
        //封装sku基本信息及其分类信息到skuEs中(属性名不一致,不方便用BeanUtils)
        SkuEs skuEs = new SkuEs();
        if (category != null) {
            skuEs.setCategoryId(category.getId());
            skuEs.setCategoryName(category.getName());
        }
        skuEs.setId(skuInfo.getId());//防止category为空，故使用skuEs.getCategoryName()
        skuEs.setKeyword(skuInfo.getSkuName() + "," + skuEs.getCategoryName());
        skuEs.setWareId(skuInfo.getWareId());
        skuEs.setIsNewPerson(skuInfo.getIsNewPerson());
        skuEs.setImgUrl(skuInfo.getImgUrl());
        skuEs.setTitle(skuInfo.getSkuName());
        skuEs.setSkuType(skuInfo.getSkuType());
        //普通商品
        if (skuInfo.getSkuType().equals(SkuType.COMMON.getCode())) {
            skuEs.setPrice(skuInfo.getPrice().doubleValue());
            skuEs.setStock(skuInfo.getStock());
            skuEs.setSale(skuInfo.getSale());
            skuEs.setPerLimit(skuInfo.getPerLimit());
        }
        //TODO 秒杀商品逻辑

        //保存sku基本信息及其分类信息到ES中
        skuRepository.save(skuEs);
    }

    @Override
    public void deleteByIds(List<Long> skuIds) {
        skuIds.forEach(this::deleteById);
    }

    @Override
    public List<SkuEs> getHotSkuInfoByCount(Integer number) {
        //SpringData中分页的第一页为0
        Pageable pageable = PageRequest.of(0, number);
        //查询只需要按规范命名方法即可
        //参考文章：https://blog.csdn.net/qq_28289405/article/details/82382441
        Page<SkuEs> pageResult = skuRepository.findByOrderByHotScoreDesc(pageable);
        return pageResult.getContent();
    }

    @Override
    public Page<SkuEs> getSkuListByPage(Pageable pageParma, SkuEsQueryVo skuEsQueryVo) {
        // 构造查询条件
        // 分类 id 必须 查询关键字 可空
        // 仓库 id 必须 从 AuthContextHolder 获取
        if (skuEsQueryVo.getWareId() == null) {
            skuEsQueryVo.setWareId(AuthContextHolder.getWareId());
        }
        String keyword = skuEsQueryVo.getKeyword();
        Page<SkuEs> result;
        log.debug("keyword:{}", keyword);
        // keyword 不为空与为空时进行的查询不同
        if (StringUtils.isEmpty(keyword)) {
            // keyword为空根据仓库id和分类id查询 参数顺序要与查询方法名一致
            log.debug("go to case: StringUtils.isEmpty(keyword)");
            log.debug("wareId:{}", skuEsQueryVo.getWareId());
            result = skuRepository.findByCategoryIdAndWareId(
                    skuEsQueryVo.getCategoryId(),
                    skuEsQueryVo.getWareId(),
                    pageParma);
        } else {
            // keyword 不为空 根据仓库id和关键字查询
            result = skuRepository.findByCategoryIdAndKeyword(
                    skuEsQueryVo.getCategoryId(),
                    skuEsQueryVo.getKeyword(),
                    pageParma);
        }
        if (CollectionUtils.isEmpty(result.getContent())) {
            return result;
        }
        // 获取 skuEs List 关联的促销规则(目前是活动规则)
        Map<Long, List<String>> activitySimpleInfo = activityFeignClient.getActivitySimpleInfo(
                result.getContent().stream().map(SkuEs::getId).collect(Collectors.toList())
        );
        // 设置 skuEs List 关联的促销规则(目前是活动规则)
        result.getContent().forEach(skuEs -> skuEs.setRuleList(activitySimpleInfo.get(skuEs.getId())));

        return result;
    }

    @Override
    public void plusSkuHotScore(Long skuId) {
        //ES 更新效率低使用redis优化，当redis中的 hotScore为10的倍数时才更新ES
        String key = "hotScore";
        //opsForZSet().incrementScore 对有序集合中指定成员的分数进行增加,如果成员不存在，则创建该成员。返回增加后的分数
        Double score = redisTemplate.opsForZSet().incrementScore(key,//有序集合的键（Key），用于标识这个有序集合。
                "skuId:" + skuId,//有序集合中的成员（Member），通常是一个字符串
                1);//要增加的分数（Score），可以是正数或负数
        if (score == null) {
            throw new RuntimeException("plusSkuHotScore(): 更新 redis sku 热度失败");
        }
        long s = Math.round(score);
        if (s % 10 == 0) {
            Optional<SkuEs> optional = skuRepository.findById(skuId);
            SkuEs skuEs = optional.orElseThrow(() -> new RuntimeException("ES 中不存在 skuId 为: " + skuId + " 的sku信息"));
            skuEs.setHotScore(s);
            skuRepository.save(skuEs);
        }
    }
}
